//
//  YYProvider.swift
//  yystory
//
//  Created by Liujinlong on 2018/11/8.
//  Copyright © 2018 lazyaudio. All rights reserved.
//

import Foundation
import Moya

class ApiProvider<Target: TargetType>: MoyaProvider<Target> {
    var requestTime: Date!
    public typealias SuccessBlcokClosure = (LMBaseParser) -> Void
    public typealias FailureBlcokClosure = (LMNetworkError) -> Void
    
    public var successCallback: SuccessBlcokClosure!
    public var failureCallback: FailureBlcokClosure!
    public var target: Target?
    fileprivate var cancellable: Cancellable?
    
    @discardableResult
    func startRequest(_ target: Target, success successCallback: @escaping SuccessBlcokClosure, failure failureCallback: @escaping FailureBlcokClosure) -> Cancellable {
        requestTime = Date()
        self.target = target
        self.successCallback = successCallback
        self.failureCallback = failureCallback

        if self.cancellable == nil {
            self.cancellable = super.request(target) { (result) in
                switch result {
                case let .success(response):
                    if let cancellable = self.cancellable, cancellable.isCancelled == false {
						self.handleSuccess(response: response)
                    }
                case let .failure(error):
                    if let cancellable = self.cancellable, cancellable.isCancelled == false {
						self.handleFailure(error: error)
                    }
                }
            }
        } else {
            super.request(target) { (result) in
                switch result {
                case let .success(response):
                    if let cancellable = self.cancellable, cancellable.isCancelled == false {
						self.handleSuccess(response: response)
                    }
                case let .failure(error):
                    if let cancellable = self.cancellable, cancellable.isCancelled == false {
						self.handleFailure(error: error)
                    }
                }
            }
        }
        return self.cancellable!
    }
    
    func startRequestaaa(_ target: Target, success successCallback: SuccessBlcokClosure, failure failureCallback: FailureBlcokClosure) {
        requestTime = Date()
        self.target = target
        
    }
    
	func handleFailure(error: MoyaError) {
        
        var networkError: LMNetworkError = LMNetworkError.other(error)
        
        switch error {
        case .jsonMapping(let response):
            networkError = LMNetworkError.jsonMapping(response)
        case .statusCode(let response):
            networkError = LMNetworkError.httpStatusCode(response)
        case .underlying(let underlyingError, _):
            if let urlError = underlyingError as? URLError {
                if urlError.code == .cancelled {
                    return
                } else {
                    networkError = LMNetworkError.error(code: urlError.code.rawValue, msg: urlError.localizedDescription)
                }
            }
        default:
            break
        }
        
        self.failureCallback(networkError)
        
    }
    
	func handleSuccess(response: Response) {
        
        var stateCode: Int?
        do {
            //如果数据返回成功则直接将结果转为JSON
            let parser: LMBaseParser?
            let json = try response.mapJSON()
            if let json = json as? [String: Any],
                let code = json["status"] as? Int {
                stateCode = code
            }
            
            if let baseTarget = self.target as? LMBaseRequest {
                parser = baseTarget.parser
            } else {
                parser = LMBaseParser()
            }
            
            let error = parser?.parserResponseJSONObject(json, data: response.data)
            if error != nil {
                self.failureCallback(error!)
            } else {
                self.successCallback(parser!)
            }
            
        } catch let error {
            if let error = error as? MoyaError {
				self.handleFailure(error: error)
            } else {
                self.failureCallback(LMNetworkError.jsonMapping(response))
            }
        }
    }
    
}

